#pragma once
#include "stdafx.h"
#include "ETHFram.h"

class CTcpConnect
{
public:
	CTcpConnect(std::string filename, int32_t totalsize);
	~CTcpConnect();

	//INT32 GetBufferSize() { return mTotalSize; }
	BOOL AddPacket(CETHFram*pkt);
	CETHFram* GetExpectPacket(ULONG seq);
	void Clear();

private:
	std::list<CETHFram*> mPktQueue;
	//UINT32 mTotalSize;
};

class CTcpSession
{
public:
	CTcpSession(const iphdr_t*iphdr, const tcphdr_t *tcphdr);
	~CTcpSession();

	INT32 HandlePacket(CETHFram*pkt, const iphdr_t*iphdr, const tcphdr_t *tcphdr, const uchar* payload, const uint32_t payloadlen);
private:
	typedef enum {
		CnDir_Up = 0,
		CnDir_Down,
		CnDir_MAX
	}LinkMode;

	typedef enum {
		CnState_NONE = 0,
		CnState_HandShark,
		CnState_WaitPacket,
		CnState_Complete
	} ConnectState_t;

	CTcpConnect*mUpLinkConnect;
	CTcpConnect*mDownLinkConnect;
	iphdr_t		mIpHdr;
	tcphdr_t	mTcpHdr;
	ConnectState_t mSessionState;
	BOOL		mChunked;

	std::string mRequestContent;
#define DEFAULTBUFFERSIZE	10*1024
	char* mBuffer;
	u_long mExpectSeq;
	UINT32 mBufflen;
	INT32 mPos;
	INT32 mChunkOffset;

	void Dump2File(std::string& filename, char*buf, INT32 size, std::ios_base::openmode mode);
	INT32 CopyPayload2Buffer(char*buffer, INT32 bufSize, INT32 &bufPos, const uchar*payload, INT32 pldLen, INT32 &offset, BOOL chunk = FALSE);
};


class CTCPSessionMgr
{
public:
	CTCPSessionMgr();
	~CTCPSessionMgr();

	static bool Initial();

	static CTcpSession* AddSession(const iphdr_t *iphdr, const tcphdr_t *tcphdr);
	static CTcpSession* GetSession(const iphdr_t *iphdr, const tcphdr_t *tcphdr);
	static bool CloseSession(const iphdr_t *iphdr, const tcphdr_t *tcphdr);

private:
#if 0//_MSC_PLATFORM_TOOLSET > 100
	static std::mutex gPoolLock;
#else
	static CRITICAL_SECTION gPoolLock;
#endif
	static std::unordered_map<std::string, CTcpSession*> gSessionPool;
};
